package com.atguigu.gmall.realtime.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.flink.api.java.tuple.Tuple2;
import redis.clients.jedis.Jedis;

import java.util.List;

/**
 * Author: Felix
 * Date: 2022/4/27
 * Desc: 查询维度信息的工具类
 */
public class DimUtil {
    public static JSONObject getDimInfo(String tableName, String id) {
        return getDimInfo(tableName,Tuple2.of("id",id));
    }
    /*
        获取维度数据    优化：旁路缓存
        思路：获取维度数据的时候，先从缓存中进行查询，如果缓存中存在维度数据，直接将缓存中的数据返回，缓存命中；如果缓存中不存在要查询的维度，
             再发送请求，到phoenix表中查询维度数据，并将查询的维度数据保存到缓存
        缓存产品的选择：
            状态：    堆内存、性能好、维护不方便
            Redis：  性能也不差，维护方便  √
        注意：
            缓存要设过期时间，不然冷数据会常驻缓存浪费资源
            要考虑维度数据是否会发生变化，如果发生变化要主动清除缓存
        Redis中存放数据的类型：
            String
        Redis中存放数据的key：
            dim:维度表表名:主键值1_主键值2
    */
    public static JSONObject getDimInfo(String tableName, Tuple2<String, String>... colNameAndValues) {
        //拼接从Redis中查询数据的key
        StringBuilder redisKey = new StringBuilder("dim:" + tableName.toLowerCase() + ":");

        StringBuilder selectDimSql = new StringBuilder("select * from " + tableName + " where ");
        for (int i = 0; i < colNameAndValues.length; i++) {
            Tuple2<String, String> colNameAndValue = colNameAndValues[i];
            String columnName = colNameAndValue.f0;
            String columnValue = colNameAndValue.f1;
            redisKey.append(columnValue);
            selectDimSql.append(columnName + " = '" + columnValue + "' ");
            if (i < colNameAndValues.length - 1) {
                redisKey.append("_");
                selectDimSql.append(" and ");
            }
        }

        Jedis jedis = null;
        String dimInfoStr = null;
        JSONObject dimInfoJsonObj = null;

        try {
            //从Redis缓存中查询数据
            jedis = RedisUtil.getJedis();
            dimInfoStr = jedis.get(redisKey.toString());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("~从Redis中查询维度数据发生了异常~");
        }

        //判断缓存中是否存在维度数据
        if(dimInfoStr != null && dimInfoStr.length() > 0){
            //缓存命中      直接将缓存中查询出来的json字符串  转换为对象  进行返回
            dimInfoJsonObj = JSON.parseObject(dimInfoStr);
        }else{
            //没有命中缓存    发送请求，到phoenix表中查询维度数据
            System.out.println("从Phoenix表中查询维度的SQL:" + selectDimSql);
            //底层还是调用的PhoenixUtil
            List<JSONObject> dimList = PhoenixUtil.queryList(selectDimSql.toString(), JSONObject.class);
            if (dimList != null && dimList.size() > 0) {
                //因为我们根据主键进行的查询，所以查询出来的结果如果不为空，只会存在1条
                dimInfoJsonObj = dimList.get(0);
                //将查询的维度数据保存到缓存
                if(jedis != null){
                    jedis.setex(redisKey.toString(),3600*24,dimInfoJsonObj.toJSONString());
                }
            } else {
                System.out.println("没有找到对应的维度数据:" + selectDimSql);
            }
        }
        //关闭Redis客户端
        if(jedis != null){
            System.out.println("~~~关闭Jedis客户端~~~");
            jedis.close();
        }

        return dimInfoJsonObj;
    }

    //获取维度数据的基本实现   select * from dim_base_trademark where id = '15' and tm_name='aaa'
    public static JSONObject getDimInfoNoCache(String tableName, Tuple2<String, String>... colNameAndValues) {
        StringBuilder selectDimSql = new StringBuilder("select * from " + tableName + " where ");
        for (int i = 0; i < colNameAndValues.length; i++) {
            Tuple2<String, String> colNameAndValue = colNameAndValues[i];
            String columnName = colNameAndValue.f0;
            String columnValue = colNameAndValue.f1;
            selectDimSql.append(columnName + " = '" + columnValue + "' ");
            if (i < colNameAndValues.length - 1) {
                selectDimSql.append(" and ");
            }
        }

        System.out.println("从Phoenix表中查询维度的SQL:" + selectDimSql);

        //底层还是调用的PhoenixUtil
        List<JSONObject> dimList = PhoenixUtil.queryList(selectDimSql.toString(), JSONObject.class);
        JSONObject dimInfoJsonObj = null;
        if (dimList != null && dimList.size() > 0) {
            //因为我们根据主键进行的查询，所以查询出来的结果如果不为空，只会存在1条
            dimInfoJsonObj = dimList.get(0);
        } else {
            System.out.println("没有找到对应的维度数据:" + selectDimSql);
        }
        return dimInfoJsonObj;
    }

    //删除已经缓存的数据
    public static void delCached(String tableName,String id){
        String redisKey = "dim:" + tableName.toLowerCase() + ":" + id;
        Jedis jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            jedis.del(redisKey);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("~~~从Redis缓存中删除数据失败~~~");
        } finally {
            if(jedis != null){
                System.out.println("~~~删除缓存后，关闭Jedis客户端~~~");
                jedis.close();
            }
        }
    }

    public static void main(String[] args) {
        //JSONObject dimInfo = getDimInfoNoCache("dim_base_trademark", Tuple2.of("id", "15"));
        //JSONObject dimInfo = getDimInfo("dim_base_trademark", Tuple2.of("id", "15"));
        JSONObject dimInfo = getDimInfo("dim_base_trademark", "15");
        System.out.println(dimInfo);
    }
}
